package cn.zzdt4j.config.service.biz.impl;

import cn.hutool.core.util.StrUtil;
import cn.zzdt4j.common.extension.enums.DelEnum;
import cn.zzdt4j.common.toolkit.BeanUtil;
import cn.zzdt4j.config.mapper.ItemInfoMapper;
import cn.zzdt4j.config.model.ItemInfo;
import cn.zzdt4j.config.model.biz.item.ItemQueryReqDTO;
import cn.zzdt4j.config.model.biz.item.ItemRespDTO;
import cn.zzdt4j.config.model.biz.item.ItemSaveReqDTO;
import cn.zzdt4j.config.model.biz.item.ItemUpdateReqDTO;
import cn.zzdt4j.config.model.biz.threadpool.ThreadPoolRespDTO;
import cn.zzdt4j.config.service.biz.ItemService;
import cn.zzdt4j.config.service.biz.ThreadPoolService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.List;

/**
 * The type Item service.
 *
 * @author by <a href="mailto:ligang941012@gmail.com">gang.Li</a>
 * @since 2023 /11/7 20:06
 */
@Service
@AllArgsConstructor
public class ItemServiceImpl implements ItemService {

    private final ItemInfoMapper itemInfoMapper;

    private final ThreadPoolService threadPoolService;

    @Override
    public void deleteItem(String namespace, String itemId) {
        List<ThreadPoolRespDTO> itemList = threadPoolService.getThreadPoolByItemId(itemId);
        if (CollectionUtils.isNotEmpty(itemList)) {
            throw new RuntimeException("项目包含线程池引用, 删除失败.");
        }
        int updateResult = itemInfoMapper.update(new ItemInfo(),
                Wrappers.lambdaUpdate(ItemInfo.class)
                        .eq(ItemInfo::getTenantId, namespace)
                        .eq(ItemInfo::getItemId, itemId)
                        .set(ItemInfo::getDelFlag, DelEnum.DELETE.getIntCode()));
        boolean retBool = SqlHelper.retBool(updateResult);
        if (!retBool) {
            throw new RuntimeException("Delete error.");
        }
    }

    @Override
    public void updateItem(ItemUpdateReqDTO reqDTO) {
        ItemInfo itemInfo = BeanUtil.convert(reqDTO, ItemInfo.class);
        int updateResult = itemInfoMapper.update(itemInfo,
                Wrappers.lambdaUpdate(ItemInfo.class)
                        .eq(ItemInfo::getTenantId, reqDTO.getTenantId())
                        .eq(ItemInfo::getItemId, reqDTO.getItemId()));
        if (!SqlHelper.retBool(updateResult)) {
            throw new RuntimeException("Update error.");
        }
    }

    @Override
    public void saveItem(ItemSaveReqDTO reqDTO) {
        LambdaQueryWrapper<ItemInfo> queryWrapper = Wrappers.lambdaQuery(ItemInfo.class)
                .eq(ItemInfo::getItemId, reqDTO.getItemId());
        // It is currently a single application, and it will support switching distributed locks during cluster deployment in the future.
        synchronized (ItemService.class) {
            ItemInfo existItemInfo = itemInfoMapper.selectOne(queryWrapper);
            Assert.isNull(existItemInfo, "项目配置已存在.");
            ItemInfo itemInfo = BeanUtil.convert(reqDTO, ItemInfo.class);
            int insertResult = itemInfoMapper.insert(itemInfo);
            if (!SqlHelper.retBool(insertResult)) {
                throw new RuntimeException("Save error");
            }
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public IPage<ItemRespDTO> queryItemPage(ItemQueryReqDTO reqDTO) {
        final LambdaQueryWrapper<ItemInfo> wrapper = Wrappers.lambdaQuery(ItemInfo.class)
                .eq(StrUtil.isNotEmpty(reqDTO.getItemId()), ItemInfo::getItemId, reqDTO.getItemId())
                .eq(StrUtil.isNotEmpty(reqDTO.getItemName()), ItemInfo::getItemName, reqDTO.getItemName())
                .eq(StrUtil.isNotEmpty(reqDTO.getTenantId()), ItemInfo::getTenantId, reqDTO.getTenantId())
                .eq(StrUtil.isNotEmpty(reqDTO.getOwner()), ItemInfo::getOwner, reqDTO.getOwner())
                .orderByDesc(reqDTO.getDesc() != null, ItemInfo::getGmtCreate);
        Page<ItemInfo> resultPage = itemInfoMapper.selectPage(reqDTO, wrapper);
        return resultPage.convert(each -> BeanUtil.convert(each, ItemRespDTO.class));
    }

    @Override
    public List<ItemRespDTO> queryItem(ItemQueryReqDTO reqDTO) {
        final LambdaQueryWrapper<ItemInfo> wrapper = Wrappers.lambdaQuery(ItemInfo.class)
                .eq(StrUtil.isNotEmpty(reqDTO.getItemId()), ItemInfo::getItemId, reqDTO.getItemId())
                .eq(StrUtil.isNotEmpty(reqDTO.getTenantId()), ItemInfo::getTenantId, reqDTO.getTenantId());
        final List<ItemInfo> itemInfos = itemInfoMapper.selectList(wrapper);
        return BeanUtil.convert(itemInfos, ItemRespDTO.class);
    }
}
